package servlets;

import java.io.IOException;
import java.util.ArrayList;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import beans.Account;
import beans.Box;
import beans.Comment;
import beans.Thread;
import dao.AccountDAO;
import dao.BoxDAO;
import dao.CommentDAO;
import dao.ThreadDAO;

/**
 * Servlet implementation class Thread
 */
@WebServlet("/thread")
public class ThreadServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private Account acc;

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		processer(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		processer(request, response);
	}

	// TODO processer
	public void processer(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("utf-8");
		String action = request.getParameter("do");
		initAccount(request);
		if (action != null) {
			if (!action.equals("")) {
				switch (action) {
				case "comment":
					doComment(request, response);
					break;
				case "post":
					request.getRequestDispatcher("create_thread").forward(
							request, response);
					break;
				case "create": // create new thread
					createThread(request, response);
					break;
				case "del":
					deleteThread(request, response);
					break;
				case "delc":
					deleteComment(request, response);
					break;
				case "view":
					viewThread(request, response);
					break;
				case "list": // view threads in box
					viewBox(request, response);
					break;
				case "edit":
					edit(request, response);
					break;
				case "save":
					save(request, response);
					break;
				case "setting":
					doSetting(request, response);
					break;
				}
				return;
			}
		}
		response.sendError(404);
	}

	private void doSetting(HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		String action = request.getParameter("action");
		String sql = "";
		switch (action) {
		case "caution":
			sql = "UPDATE thread SET state=(CASE WHEN state=1 THEN 0 WHEN state=2 THEN -1 WHEN state=-1||state=4 THEN 2 WHEN state=0||state=3 THEN 1 END) WHERE id=?";
			break;
		case "hide":
			sql = "UPDATE thread SET state=(CASE WHEN state=3 THEN 0 WHEN state=4 THEN -1 WHEN state=0||state=1 THEN 3 WHEN state=-1||state=2 THEN 4 ELSE thread.state END) WHERE id=?";
			break;
		case "close":
			sql = "UPDATE thread SET state=(CASE WHEN state=-1 THEN 0 WHEN state=2 THEN 1 WHEN state=4 THEN 3 WHEN state=0 THEN -1 WHEN state=1 THEN 2 ELSE 4 END) WHERE id=?";
			break;
		}
		try {
			int threadId = Integer.parseInt(request.getParameter("tid"));
			ThreadDAO.settings(sql, threadId);

			response.sendRedirect("thread?do=list&bid="
					+ request.getParameter("bid"));
		} catch (NumberFormatException e) {
			e.printStackTrace();
			response.sendError(404);
		}
	}

	private void save(HttpServletRequest request, HttpServletResponse response)
			throws IOException {
		String type = request.getParameter("type");

		if (type.equalsIgnoreCase("thread")) {
			int threadId = Integer.parseInt(request.getParameter("tid"));
			String title = request.getParameter("title");
			String content = request.getParameter("content");
			ThreadDAO.update(threadId, title, content);

			response.sendRedirect("thread?do=view&tid="
					+ request.getParameter("tid"));
		} else if (type.equalsIgnoreCase("comment")) {
			int commentId = Integer.parseInt(request.getParameter("cid"));
			String content = request.getParameter("content");
			CommentDAO.update(commentId, content);

			response.sendRedirect("thread?do=view&tid="
					+ request.getParameter("tid"));
		}
	}

	private void edit(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String type = request.getParameter("type");
		switch (type) {
		case "thread":
			int threadId = Integer.parseInt(request.getParameter("tid"));
			Thread thread = ThreadDAO.selectSumaryThread(threadId);

			request.setAttribute("obj", thread);
			request.getRequestDispatcher("Edit.jsp?type=thread").forward(
					request, response);
			break;
		case "comment":
			int commentId = Integer.parseInt(request.getParameter("cid"));
			Comment comment = CommentDAO.selectById(commentId);

			request.setAttribute("obj", comment);
			request.getRequestDispatcher("Edit.jsp?type=comment").forward(
					request, response);
			break;
		}
	}

	private void viewBox(HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		try {
			int boxId = Integer.parseInt(request.getParameter("bid"));
			Box box = BoxDAO.selectById(boxId);

			if (box == null) {
				response.sendError(404);
				return;
			}

			ArrayList<Thread> threads = ThreadDAO.selectNoteThread(boxId);

			int currentPage = 1;
			try {
				if ((currentPage = Integer.parseInt(request.getParameter("p"))) < 1) {
					currentPage = 1;
				}
			} catch (NumberFormatException e) {
				// to do something
			}
			request.setAttribute("cPage", currentPage);

			int size = 15; // default value
			try {
				size = Integer.parseInt(request.getParameter("sz"));
				if (size < 1)
					size = 1;
			} catch (NumberFormatException e) {
				// to do something
			}
			request.setAttribute("size", size);

			ArrayList<Thread> normalThread = ThreadDAO.selectNormalThread(
					boxId, currentPage * size - size, size);
			threads.addAll(normalThread);

			box.setThreads(threads);
			request.setAttribute("box", box);

			int numRow = BoxDAO.selectSumThreadInBox(boxId);
			int numPage = (int) Math.ceil(numRow * 1.0 / size);
			request.setAttribute("sumPage", numPage > 0 ? numPage : 1);

			request.getRequestDispatcher("box?bid=" + boxId).forward(request,
					response);
		} catch (NumberFormatException e) {
			e.printStackTrace();
			response.sendError(404);
		}
	}

	private void viewThread(HttpServletRequest request,
			HttpServletResponse response) throws IOException, ServletException {
		try {
			int threadId = Integer.parseInt(request.getParameter("tid"));
			Thread thread = ThreadDAO.selectById(threadId);

			if (thread == null) {
				// unknown thread in database
				response.sendError(404);
				return;
			}

			int currentPage = 1;
			try {
				if ((currentPage = Integer.parseInt(request.getParameter("p"))) < 1) {
					currentPage = 1;
				}
			} catch (NumberFormatException e) {
				// to do something
			}
			request.setAttribute("cPage", currentPage);

			int size = 10;
			try {
				size = Integer.parseInt(request.getParameter("sz"));
				if (size < 1)
					size = 10;
			} catch (NumberFormatException e) {
				// to do something
			}
			request.setAttribute("size", size);

			int sumPage = 1;
			int sumReply = 0;

			sumReply = thread.getReply();
			sumPage = (int) Math.ceil(sumReply * 1.0 / size);
			request.setAttribute("sumPage", sumPage > 0 ? sumPage : 1);

			ArrayList<Comment> comments = CommentDAO.selectByThreadId(threadId,
					currentPage * size - size, size);
			thread.setComments(comments);
			request.setAttribute("thread", thread);

			ThreadDAO.updateSee(threadId);

			request.getRequestDispatcher("Thread.jsp").forward(request,
					response);
		} catch (NumberFormatException e) {
			e.printStackTrace();
			response.sendError(404);
		}
	}

	private void deleteComment(HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		if (acc.isType("admin")) {
			int cid = Integer.parseInt(request.getParameter("cid"));
			CommentDAO.deleteById(cid);
			// remove update posts in member

			response.sendRedirect("thread?do=view&tid="
					+ request.getParameter("tid"));
		} else {
			// FIXME notify
		}
	}

	private void deleteThread(HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		if (acc.isType("admin")) {
			int threadId = Integer.parseInt(request.getParameter("tid"));
			ThreadDAO.deleteById(threadId);
			// remove update posts in member

			response.sendRedirect("thread?do=list&bid="
					+ request.getParameter("bid"));
		} else {
			// FIXME notify
		}
	}

	private void createThread(HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		initAccount(request);
		String title = request.getParameter("title");
		String content = request.getParameter("content");
		if (acc == null || title.equals("") || content.equals("")) {
			response.sendError(404);
			return;
		}
		try {
			int boxId = Integer.parseInt(request.getParameter("bid"));
			boolean rs = ThreadDAO.insert(acc.getId(), boxId, title, content);
			if (rs) {
				AccountDAO.updatePosts(acc.getId());
			}

			response.sendRedirect("thread?do=list&bid="
					+ request.getParameter("bid"));
		} catch (NumberFormatException e) {
			e.printStackTrace();
			response.sendError(404);
		}
	}

	private void doComment(HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		int threadId = Integer.parseInt(request.getParameter("tid"));
		String content = request.getParameter("content");

		CommentDAO.insert(threadId, acc.getId(), content);
		AccountDAO.updatePosts(acc.getId());

		response.sendRedirect("thread?do=view&tid="
				+ request.getParameter("tid"));
	}

	public void initAccount(HttpServletRequest request) {
		if (acc == null)
			acc = (Account) request.getSession().getAttribute("account");
	}
}
